/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.yonsei.iwb.smarttv.query;

import edu.yonsei.iwb.smarttv.util.SMARTTVLog;
import java.util.Vector;
import kr.ac.kaist.swrc.jhannanum.comm.Eojeol;
import kr.ac.kaist.swrc.jhannanum.comm.Sentence;
import kr.ac.kaist.swrc.jhannanum.exception.ResultTypeException;
import kr.ac.kaist.swrc.jhannanum.hannanum.Workflow;
import kr.ac.kaist.swrc.jhannanum.hannanum.WorkflowFactory;

/**
 *
 * @author Onlyjiny
 */
public class TermAnalyzer {

    private final String REGEXP_FOR_SPECIAL_CHARACTER = "[^\uAC00-\uD7A3xfe0-9a-zA-Z\\s]";
    private static TermAnalyzer ta;
    private int sentenceID = 0;
    private Workflow workflow;

    public TermAnalyzer() {
        this.activateWorkflow();
    }

    public static TermAnalyzer getTermAnalyzer() {
        if (ta == null) {
            TermAnalyzer.ta = new TermAnalyzer();
        }
        return TermAnalyzer.ta;
    }

    public boolean activateWorkflow() {
        try {
            workflow = WorkflowFactory.getPredefinedWorkflow(WorkflowFactory.WORKFLOW_HMM_POS_TAGGER);
            workflow.activateWorkflow(true);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public boolean deactivateWorkflow() {
        try {
            workflow.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public Vector<String> getIndexTerms(String sentence) {
        Vector<String> result = this.getTerms(sentence);
//        // 형태소 분석된 결과를 이용하여 단어 조합을 생성
//        result.addAll(this.expandCombination(result));
//        // 공백을 기준으로 단어의 조합을 생성, ex> 공주의 남자 --> 공주의남자
//        String[] splitSentence = sentence.replaceAll(this.REGEXP_FOR_SPECIAL_CHARACTER, "").split(" ");
//        result.addAll(this.expandCombination(splitSentence));
        return result;
    }

    private Vector<String> expandCombination(String[] data) {
        Vector<String> result = new Vector<String>();
        for (int i = 2; i <= data.length; i++) {
            boolean[] used = new boolean[data.length];
            doExpandCombination(data, used, i, 0, result);
        }
        return result;
    }

    private void doExpandCombination(String[] data, boolean[] used, int selectionNumber, int startIndex, Vector<String> result) {
        if (selectionNumber == 0) {
            String s = new String();
            for (int i = 0; i < used.length; i++) {
                if (used[i]) {
                    s = s + data[i];
                }
            }
            result.add(s);
            return;
        }
        for (int i = startIndex; i <= data.length - selectionNumber; i++) {
            used[i] = true;
            doExpandCombination(data, used, selectionNumber - 1, i + 1, result);
            used[i] = false;
        }
    }

    private Vector<String> expandCombination(Vector<String> data) {
        Vector<String> result = new Vector<String>();
        for (int i = 2; i <= data.size(); i++) {
            boolean[] used = new boolean[data.size()];
            doExpandCombination(data, used, i, 0, result);
        }
        return result;
    }

    private void doExpandCombination(Vector<String> data, boolean[] used, int selectionNumber, int startIndex, Vector<String> result) {
        if (selectionNumber == 0) {
            String s = new String();
            for (int i = 0; i < used.length; i++) {
                if (used[i]) {
                    s = s + data.get(i);
                }
            }
            result.add(s);
            return;
        }
        for (int i = startIndex; i <= data.size() - selectionNumber; i++) {
            used[i] = true;
            doExpandCombination(data, used, selectionNumber - 1, i + 1, result);
            used[i] = false;
        }
    }

    public Vector<String> getQueryTerms(String sentence) {
        Vector<String> result = this.getTerms(sentence);
        return result;
    }

        public Eojeol[] getEojeol(String oldsentence) throws ResultTypeException{
        String sentence = oldsentence.replace(".", " ").replace("?", " ").replace("!", " ").replace("-", " ").replace("_", " ").replace("(", " ").replace(")", " ");
        Eojeol[] eojeolArray ;
        workflow.analyze(sentence);
        Sentence resultSentence = workflow.getResultOfSentence(new Sentence(sentenceID++, sentenceID, false));
        eojeolArray = resultSentence.getEojeols();
        return eojeolArray;
    }
        
    private Vector<String> getTerms(String oldsentence) {
        String sentence = oldsentence.replace(".", " ").replace("?", " ").replace("!", " ").replace("-", " ").replace("_", " ").replace("(", " ").replace(")", " ");

        Vector<String> result = new Vector<String>();
        try {
            workflow.analyze(sentence);
            SMARTTVLog.log(SMARTTVLog.DETAIL, "Result of Sentence \"" + sentence + "\" Analyze by HanNanum: ");
            Sentence resultSentence = workflow.getResultOfSentence(new Sentence(sentenceID++, sentenceID, false));
            Eojeol[] eojeolArray = resultSentence.getEojeols();
            for (int i = 0; i < eojeolArray.length; i++) {
                if (eojeolArray[i].length > 0) {
                    String[] morphemes = eojeolArray[i].getMorphemes();
                    String[] tags = eojeolArray[i].getTags();
                    // 공백이 없는 문자열에서 분리된 명사를 각각의 다른 용어로 구분하여 고려하는 방법
                    // "혹성탈출" --> "혹성," "탈출"
                    for (int j = 0; j < morphemes.length; j++) {
                        SMARTTVLog.log(SMARTTVLog.DETAIL, morphemes[j] + "-" + tags[j] + ", ");
                        if (HanNanumMorphemeTag.useMorpheme(tags[j])) {
                            result.add(morphemes[j].toLowerCase());
                        }
                    }
//                    // 공백이 없는 문자열에서 분리된 명사를 하나의 명사로 합쳐서 고려하는 방법
//                    // "혹성탈출" --> "혹성," "탈출" --> "혹성탈출"
//                    String temp = new String();
//                    SMARTTVLog.log(SMARTTVLog.DETAIL, "Sentence for HanNanum: " + sentence + "\n");
//                    for (int j = 0; j < morphemes.length; j++) {
//                        SMARTTVLog.log(SMARTTVLog.DETAIL, "\t" + morphemes[j] + " / " + tags[j] + "\n");
//                        if (HanNanumMorphemeTag.useMorpheme(tags[j])) {
//                            temp += morphemes[j];
//                        }
//                    }
//                    result.add(temp);
                }
            }
            SMARTTVLog.log(SMARTTVLog.DETAIL, "\n");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static void main(String args[]) {
        TermAnalyzer qa = new TermAnalyzer();
        Vector<String> v = qa.getIndexTerms("최종병기 활 영화감독이 제작한 영화");
        for (int i = 0; i < v.size(); i++) {
            System.out.println(v.get(i));
        }
        qa.deactivateWorkflow();
    }
}
